package net.lb.io.json.serializer;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import net.lb.baseutil.collection.ObjectCollect;
import net.lb.baseutil.collection.StringCache;
import net.lb.io.json.JsonObject;
import net.lb.io.json.field.JsonField;
import net.lb.io.json.util.CycleException;
import net.lb.io.json.util.JsonSerializer;

public class FieldContainerSerializer implements JsonSerializer
{
    JsonField[] jsonFields;
    
    public void setJsonFields(JsonField[] jsonFields)
    {
        this.jsonFields = jsonFields;
    }
    
    @Override
    public Object transToJsonvalue(Object src, ObjectCollect collect)
    {
        if (collect.add(src) == false)
        {
            throw new CycleException(src);
        }
        JsonObject jsonObject = new JsonObject();
        for (JsonField eacj : jsonFields)
        {
            eacj.tranToJsonvalue(src, jsonObject, collect);
        }
        collect.remove(src);
        return jsonObject;
    }
    
    @Override
    public void writeToString(StringCache cache, Object value, ObjectCollect collect)
    {
        if (collect.add(value))
        {
            cache.append('{', 10);
            for (JsonField each : jsonFields)
            {
                each.writeToString(cache, value, collect);
            }
            if (cache.isCommaLast())
            {
                cache.deleteLast();
            }
            cache.append('}');
            collect.remove(value);
        }
        else
        {
            throw new CycleException(value);
        }
        
    }
    
    @Override
    public Object toBean(Object json, Type type)
    {
        Object target;
        try
        {
            if (type instanceof ParameterizedType)
            {
                target = ((Class<?>) ((ParameterizedType) type).getRawType()).newInstance();
            }
            else
            {
                if (((Class<?>) type) == Object.class)
                {
                    return json;
                }
                target = ((Class<?>) type).newInstance();
            }
            for (JsonField jsonField : jsonFields)
            {
                jsonField.fillObject((JsonObject) json, target);
            }
            return target;
        }
        catch (InstantiationException | IllegalAccessException e)
        {
            throw new RuntimeException(e);
        }
    }
    
}
